package PuzzlePieces;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class SudokuPuzzle {

	
	private SudokuCol[] columns = new SudokuCol[9];
	private SudokuRow[] rows = new SudokuRow[9];
	private SudokuBox[] boxes = new SudokuBox[9];
	private boolean changed = false;
	//private ArrayList<Integer> availableNumbers = new ArrayList<Integer>(9);
	
	public SudokuPuzzle(String file){
		setupPuzzle();
		try{
			BufferedReader br = new BufferedReader(new FileReader(file));
			String input = br.readLine();
			int row = 0;
			int col = 0;
			while(input != null){
				//do stuff
				char[] numbers = input.toCharArray();
				for(int i = 0; i < 9; i++){
					setNumber(Integer.parseInt(String.valueOf(numbers[i])), row, col);
					col++;
				}
				//end of doing stuff
				row++;
				col = 0;
				input = br.readLine();
			}
			commit();
		}catch(FileNotFoundException e){
			System.err.println("File "+file+" not found!");
		}catch(IOException e){
			System.err.println("Error reading file:"+file);
		}
	}

	private void setupPuzzle() {
		// TODO Auto-generated method stub
		for(int i = 0; i < 9; i++){
			columns[i] = new SudokuCol(i);
			rows[i] = new SudokuRow(i);
			boxes[i] = new SudokuBox(((i%3)*3), (((i%3)*3)+2), ((i/3)*3), (((i/3)*3)+2));
			/*
			switch(i){
				case 0 :
					boxes[i] = new SudokuBox(0, 2, 0, 2);
					break;
				case 1 : 
					boxes[i] = new SudokuBox(3, 5, 0, 2);
					break;
				case 2 : 
					boxes[i] = new SudokuBox(6, 8, 0, 2);
					break;
				case 3 :
					boxes[i] = new SudokuBox(0, 2, 3, 5);
					break;
				case 4 : 
					boxes[i] = new SudokuBox(3, 5, 3, 5);
					break;
				case 5 : 
					boxes[i] = new SudokuBox(6, 8, 3, 5);
					break;
				case 6 :
					boxes[i] = new SudokuBox(0, 2, 6, 8);
					break;
				case 7 : 
					boxes[i] = new SudokuBox(3, 5, 6, 8);
					break;
				case 8 : 
					boxes[i] = new SudokuBox(6, 8, 6, 8);
					break;
			}
			*/
		}
		for(int i = 0; i < 9; i++){
			
			rows[i].setLeftRow(rows[((i+1)%3)+((i/3)*3)]);
			rows[i].setRightRow(rows[((i+2)%3)+((i/3)*3)]);
			columns[i].setLeftCol(columns[((i+1)%3)+((i/3)*3)]);
			columns[i].setRightCol(columns[((i+2)%3)+((i/3)*3)]);
		}
	}

	public void setNumber(int value, int row, int col) {
		// TODO Auto-generated method stub
		rows[row].setNumber(col, value);
		columns[col].setNumber(row, value);
		boxes[SudokuBox.calculateBoxID(row, col)].setNumber(row, col, value);
		changed = true;
	}
	
	public void commitNumber(int value, int row, int col){
		//rows[row].commitNumber(col, value);
		//columns[col].commitNumber(row, value);
		//boxes[SudokuBox.calculateBoxID(row, col)].commitNumber(row, col, value);
	}
	
	public String toString(){
		StringBuilder myString = new StringBuilder();
		for(int i = 0; i < 9; i++){
			myString.append(rows[i].toString());
		}
		
		return myString.toString();
	}
	
	public String tempString(){
		StringBuilder myString = new StringBuilder();
		for(int i = 0; i < 9; i++){
			myString.append(rows[i].tempString());
		}
		return myString.toString();
	}
	
	public void commit(){
		for(int i = 0; i < 9; i++){
			columns[i].commit();
			rows[i].commit();
			boxes[i].commit();
		}
	}
	
	public void reset(){
		for(int i = 0; i < 9; i++){
			columns[i].reset();
			rows[i].reset();
			boxes[i].reset();
		}
		changed = false;
	}
	
	public ArrayList<Integer> getAvailNumbers(int row, int col){
		//availableNumbers.clear();
		ArrayList<Integer> availableNumbers = new ArrayList<Integer>();
		availableNumbers.clear();
		for(int i = 0; i < 9; i++){
			Integer currentNum = new Integer(i+1);
			boolean inRow = rows[row].getUsedNumbers().contains(currentNum);
			boolean inCol = columns[col].getUsedNumbers().contains(currentNum);
			int boxID = SudokuBox.calculateBoxID(row, col);
			boolean inBox = boxes[boxID].getUsedNumbers().contains(currentNum);
			if(!inRow && !inCol	&& !inBox){
				availableNumbers.add(currentNum);
			}
		}
		return availableNumbers;
	}
	
	public ArrayList<Integer> getUsedNumbers(SudokuLine aLine, SudokuLine bLine){
		
		ArrayList<Integer> availableNumbers = new ArrayList<Integer>();
		availableNumbers.clear();
		ArrayList<Integer> aList = aLine.getUsedNumbers();
		ArrayList<Integer> bList = bLine.getUsedNumbers();
		for(int i = 0; i < bList.size(); i++){
			if(aList.contains(bList.get(i))){
				availableNumbers.add(bList.get(i));
			}
		}
		
		return availableNumbers;
	}
	

	
	public SudokuBox getBox(int row, int col){
		return boxes[SudokuBox.calculateBoxID(row, col)];
	}
	
	public SudokuCol getCol(int col){
		return columns[col];
	}
	
	public SudokuRow getRow(int row){
		return rows[row];
	}
	
	public boolean checkZero(int row, int col){
		if(rows[row].tempLine[col] == 0){
			return true;
		}else{
			return false;
		}
	}
	
	public boolean isCorrect(){
		boolean result = false;
		for(int i = 0; i < 9; i++){
			if(rows[i].correct() && columns[i].correct() && boxes[i].correct()){
				result = true;
			}else{
				result = false;
				break;
			}
		}
		return result;
	}
	
	public boolean isChanged(){
		return changed;
	}

}
